/*
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 * 
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 * 
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA

 *(C) Copyright 2006 Marvell International Ltd.  
 * All Rights Reserved 
 */

/**
**  FILENAME:       xllp_dfc_proc.h
**
**  PURPOSE: Header file for xllp DFC component. 
**           
**                   
**            
**                  
**
******************************************************************************/
#ifndef __XLLP_DFC_H
#define __XLLP_DFC_H

#include "xllp_defs.h"
#include "xllp_ost.h"
//#include "xllp_clkmgr.h"
// The Data Flash Controller Registers structure
typedef struct {
    XLLP_VUINT32_T      ndcr;         // Data Flash Control Register
    XLLP_VUINT32_T      ndtr0cs0;     // Timing Parameter 0 Register
    XLLP_VUINT32_T      resrved0;     // Reserved 0x43100008
    XLLP_VUINT32_T      ndtr1cs0;     // Timing Parameter 1 Register
    XLLP_VUINT32_T      resrved1;     // Reserved 0x43100010
    XLLP_VUINT32_T      ndsr;             // Data Controller Status Register
    XLLP_VUINT32_T      ndpcr;            // Data Controller Page Count Register
    XLLP_VUINT32_T      ndbdr0;           // Data Controller Bad Block Register 0
    XLLP_VUINT32_T      ndbdr1;           // Data Controller Bad Block Register 1
    XLLP_VUINT32_T      resrved2[7];  // Reserved 0x43100024 - 0x4310003C
    XLLP_VUINT32_T      nddb;             // Data Controller Data Register
    XLLP_VUINT32_T      resrved3;     // Reserved 0x43100044
    XLLP_VUINT32_T      ndcb0;            // Data Controller Command Buffer 0
    XLLP_VUINT32_T      ndcb1;            // Data Controller Command Buffer 1
    XLLP_VUINT32_T      ndcb2;            // Data Controller Command Buffer 2
} XLLP_DFC_REG_T, *P_XLLP_DFC_REG_T;


// The Data Flash Controller Mode structure
typedef struct {
    XLLP_UINT32_T   enableDMA;          // DMA, or nonDMA mode
    XLLP_UINT32_T   enableECC;          // ECC on/off 
    XLLP_UINT32_T   enableSpareArea;    // Spare enable
    XLLP_UINT32_T   chipSelect;         // CS0 or CS1
} XLLP_DFC_MODE_T, *P_XLLP_DFC_MODE_T;
    
typedef XLLP_INT8_T XLLP_MFP_RM_DB_ID_T, *P_XLLP_MFP_RM_DB_ID_T;

// The Data Flash Controller Flash timing structure
// For NAND flash used on Littleton board(Samsung K9K1216Q0C),
// user should use value at end of each row of following member
// ,bracketed.
typedef struct {
    XLLP_UINT32_T   tCH;        // Enable signal hold time. [10]
    XLLP_UINT32_T   tCS;        // Enable signal setup time.[0]
    XLLP_UINT32_T   tWH;        // ND_nWE high duration.[20]
    XLLP_UINT32_T   tWP;        // ND_nWE pulse time.[40]
    XLLP_UINT32_T   tRH;        // ND_nRE high duration.[20]
    XLLP_UINT32_T   tRP;        // ND_nRE pulse width.[40]
    XLLP_UINT32_T   tR;         // ND_nWE high to ND_nRE low for read.[11123]
    XLLP_UINT32_T   tWHR;       // ND_nWE high to ND_nRE low delay for status read.[110]
    XLLP_UINT32_T   tAR;        // ND_ALE low to ND_nRE low delay.[10]
} XLLP_DFC_FLASH_TIMING_T;

// The Data Flash Controller Flash specification structure
// For NAND flash used on Littleton board(Samsung K9K1216Q0C),
// user should use value at end of each row of following member
// ,bracketed.
typedef struct {
    XLLP_DFC_FLASH_TIMING_T timing;     // NAND Flash timing
    XLLP_UINT32_T   enableBusArbiter; // Data flash bus arbiter enable (ND_ARB_EN).[1]
    XLLP_UINT32_T   pagePerBlock;       // Pages per block (PG_PER_BLK). [32]
    XLLP_UINT32_T   rowAddrStart;       //  Row address start position (RA_START).[0]
    XLLP_UINT32_T   byteCntReadID;      // returned ID bytes(RD_ID_CNT).[4]
    XLLP_UINT32_T   dfcMode;                // NAND, CARBONDALE, PIXLEY... (ND_MODE)[0]
    XLLP_UINT32_T   ncsx;                       // Chip select don't care bit (NCSX).[0]
    XLLP_UINT32_T   pageSize;           // Page size in bytes (PAGE_SZ).[512]
    XLLP_UINT32_T   widthFlash;             // Width of Flash memory (DWIDTH_M).[16]
    XLLP_UINT32_T   widthDFC;         // Width of flash controller(DWIDTH_C).[16]
    XLLP_UINT32_T   numBlocks;        // Number of physical blocks in Flash.[4096]
    XLLP_UINT32_T   chipID;     // NAND chip ID
    XLLP_UINT32_T   readProgCycles;   // Read Program address cycles

    // command codes
    XLLP_UINT32_T   read1;          // Read. [0x0000]
    XLLP_UINT32_T   read2;      // unused, DFC don't support yet.[0x0050]
    XLLP_UINT32_T   program;    // two cycle command;[0x1080]
    XLLP_UINT32_T   readStatus; // [0x0070]
    XLLP_UINT32_T   readID;         // [0x0090]
    XLLP_UINT32_T   erase;        // two cycle command.[0xD060]
    XLLP_UINT32_T   reset;        // [0x00FF]
    XLLP_UINT32_T   lock;               // lock whole flash.[0x002A]
    XLLP_UINT32_T   unlock;       // two cycle command, supporting partial unlock.[0x2423]
    XLLP_UINT32_T   lockStatus; // read block lock status.[0x007A]
    XLLP_STATUS_T (* Addr2NDCB1)(XLLP_UINT16_T cmd, XLLP_UINT32_T addr, XLLP_UINT32_T *pNdcb1);
    XLLP_STATUS_T (* NDBBR2Addr)(XLLP_UINT16_T cmd, XLLP_UINT32_T ndbbr, XLLP_UINT32_T *pAddr);
} XLLP_DFC_FLASH_SPECS_T, *P_XLLP_DFC_FLASH_SPECS_T;

// The Data Flash Controller Context structure
typedef struct {
    P_XLLP_DFC_REG_T pDFCReg;    // DFC register base
    P_XLLP_DFC_MODE_T pDFCMode;   // DFC mode of operation structure
    unsigned long * pDma;     // DMA context structure used by DFC
    P_XLLP_VUINT32_T pMFPBase;   // MFPR base address
    P_XLLP_MFP_RM_DB_ID_T pMFPRmDb;     // MFP Resource Manager database
    P_XLLP_OST_T pOSTReg;     // OST reg base, for busy delay
    unsigned long * pDmacRegsBase;
    P_XLLP_DFC_FLASH_SPECS_T pFlashInfo;// Flash Spec. structure, initialized by XLLP
    
} XLLP_DFC_CONTEXT_T, *P_XLLP_DFC_CONTEXT_T;

/* add for DMA */
#define XLLP_DFC_NDCB0  0x43100048
#define XLLP_DFC_NDDB   0x43100040


// register masks

// DFC ndsr register for interrupt
#define XLLP_DFC_INT_WRCMDREQM      XLLP_BIT_0
#define XLLP_DFC_INT_RDDREQM            XLLP_BIT_1
#define XLLP_DFC_INT_WRDREQM            XLLP_BIT_2
#define XLLP_DFC_INT_SBERRM             XLLP_BIT_3
#define XLLP_DFC_INT_DBERRM             XLLP_BIT_4
#define XLLP_DFC_INT_CS1_BBDM           XLLP_BIT_5
#define XLLP_DFC_INT_CS0_BBDM           XLLP_BIT_6
#define XLLP_DFC_INT_CS1_CMDDM        XLLP_BIT_7
#define XLLP_DFC_INT_CS0_CMDDM        XLLP_BIT_8
#define XLLP_DFC_INT_CS1_PAGEDM       XLLP_BIT_9
#define XLLP_DFC_INT_CS0_PAGEDM       XLLP_BIT_10
#define XLLP_DFC_INT_RDYM                   XLLP_BIT_11

// DFC ndsr register for status
#define XLLP_DFC_STATUS_WRCMDREQ        XLLP_BIT_0
#define XLLP_DFC_STATUS_RDDREQ          XLLP_BIT_1
#define XLLP_DFC_STATUS_WRDREQ          XLLP_BIT_2
#define XLLP_DFC_STATUS_SBERR           XLLP_BIT_3
#define XLLP_DFC_STATUS_DBERR           XLLP_BIT_4
#define XLLP_DFC_STATUS_CS1_BBD         XLLP_BIT_5
#define XLLP_DFC_STATUS_CS0_BBD         XLLP_BIT_6
#define XLLP_DFC_STATUS_CS1_CMDD        XLLP_BIT_7
#define XLLP_DFC_STATUS_CS0_CMDD        XLLP_BIT_8
#define XLLP_DFC_STATUS_CS1_PAGED       XLLP_BIT_9
#define XLLP_DFC_STATUS_CS0_PAGED       XLLP_BIT_10
#define XLLP_DFC_STATUS_RDY             XLLP_BIT_11


// DFC control register
#define XLLP_DFC_CTRL_ND_ARB_EN         XLLP_BIT_12
#define XLLP_DFC_CTRL_PG_PER_BLK        XLLP_BIT_14
#define XLLP_DFC_CTRL_RA_START          XLLP_BIT_15
#define XLLP_DFC_CTRL_RD_ID_CNT         XLLP_BIT_16
#define XLLP_DFC_CTRL_CLR_ECC               XLLP_BIT_19
#define XLLP_DFC_CTRL_CLR_PG_CNT        XLLP_BIT_20
#define XLLP_DFC_CTRL_ND_MODE               XLLP_BIT_21
#define XLLP_DFC_CTRL_NCSX                  XLLP_BIT_23
#define XLLP_DFC_CTRL_PAGE_SZ               XLLP_BIT_24
#define XLLP_DFC_CTRL_DWIDTH_M          XLLP_BIT_26
#define XLLP_DFC_CTRL_DWIDTH_C          XLLP_BIT_27
#define XLLP_DFC_CTRL_ND_RUN                XLLP_BIT_28
#define XLLP_DFC_CTRL_DMA_EN                XLLP_BIT_29
#define XLLP_DFC_CTRL_ECC_EN                XLLP_BIT_30
#define XLLP_DFC_CTRL_SPARE_EN          XLLP_BIT_31

// DFC Command Buffer 0 Register
#define XLLP_DFC_NDCB_AUTO_RS           0x02000000
#define XLLP_DFC_NDCB_CSEL_0            0x00000000
#define XLLP_DFC_NDCB_CSEL_1            0x01000000

// DFC command type
typedef enum {
    XLLP_DFC_CMD_READ                   = 0x00000000,
    XLLP_DFC_CMD_PROGRAM                = 0x00200000,       
    XLLP_DFC_CMD_ERASE                  = 0x00400000,
    XLLP_DFC_CMD_READ_ID                = 0x00600000,
    XLLP_DFC_CMD_STATUS_READ            = 0x00800000,
    XLLP_DFC_CMD_RESET                  = 0x00a00000
} XLLP_DFC_CMD_TYPE_T;                            

#define XLLP_DFC_NDCB_NC                0x00100000
#define XLLP_DFC_NDCB_DBC_SINGLE        0x00000000
#define XLLP_DFC_NDCB_DBC_DOUBLE        0x00080000
#define XLLP_DFC_NDCB_ADDR_CYC_SHIFT    16

// register bit offset 

// DFC timing 0 register
#define XLLP_DFC_TIMING_tRP     0
#define XLLP_DFC_TIMING_tRH     3
#define XLLP_DFC_TIMING_tWP     8
#define XLLP_DFC_TIMING_tWH     11
#define XLLP_DFC_TIMING_tCS     16
#define XLLP_DFC_TIMING_tCH     19

// DFC timing 1 register
#define XLLP_DFC_TIMING_tAR     0
#define XLLP_DFC_TIMING_tWHR    4
#define XLLP_DFC_TIMING_tR          16

// DFC NDSR reserved bits offset
#define XLLP_DFC_NDSR_RESERVED 0xFFF
#define XLLP_DFC_NDSR_CLEAR     0xFFF

// max value for each timing setting in DFC
#define XLLP_TIMING_MAX_tCH      7
#define XLLP_TIMING_MAX_tCS      7
#define XLLP_TIMING_MAX_tWH      7
#define XLLP_TIMING_MAX_tWP      7
#define XLLP_TIMING_MAX_tRH      7
#define XLLP_TIMING_MAX_tRP      7
#define XLLP_TIMING_MAX_tR       65535
#define XLLP_TIMING_MAX_tWHR     15
#define XLLP_TIMING_MAX_tAR      15

#define CONFIG_CPU_MONAHANS_LV
// DFC clock. constantly 104M
#if   defined(CONFIG_CPU_MONAHANS_P) || defined(CONFIG_CPU_MONAHANS_PL)
#define XLLP_DFC_CLOCK  104
#elif defined(CONFIG_CPU_MONAHANS_L) || defined(CONFIG_CPU_MONAHANS_LV)
#define XLLP_DFC_CLOCK  156
#else
#error "please define DFC clock!"
#endif

// The following data is a rough evaluation
#define NAND_OTHER_TIMEOUT      20 // microsecond, for readID/readStatus/reset
#define NAND_CMD_TIMEOUT        2000000  // microsecond, for readID/readStatus/reset

// Flash Block Lock Status
#define BLOCK_STATUS_UNLOCK     0x06
#define BLOCK_STATUS_LOCK       0x02
#define BLOCK_STATUS_LOCK_TIGHT 0x01

// DFC data size enumeration transfered from/to controller, including padding
// (zero)to be a multiple of 32.
typedef enum {
    XLLP_DFC_DATA_SIZE_STATUS = 8,          // for ReadStatus/ReadBlockLockStatus
    XLLP_DFC_DATA_SIZE_ID = 7,          // for ReadID
    // PGSize = 512, SpareSize=16
    XLLP_DFC_DATA_SIZE_32 = 32,         // for read2
    XLLP_DFC_DATA_SIZE_512 = 512,       // for read/program disabling spare area
    XLLP_DFC_DATA_SIZE_520 = 520,   // for spare=1, ECC=1
    XLLP_DFC_DATA_SIZE_528 = 528,   // for spare=1, ECC=0
    XLLP_DFC_DATA_SIZE_544 = 544,       // NOT used for PIO, for read/program enabling spare area
    // PGSize = 2048, SpareSize = 64
    XLLP_DFC_DATA_SIZE_64 = 64,         // for read2
    XLLP_DFC_DATA_SIZE_2048 = 2048,     // for read/program disabling spare area
    XLLP_DFC_DATA_SIZE_2088 = 2088,     // for read/program enabling spare area with ecc
    XLLP_DFC_DATA_SIZE_2112 = 2112,     // for read/program enabling spare area, but no ecc
    XLLP_DFC_DATA_SIZE_UNUSED = 0xFFFF
} XLLP_DFC_DATA_SIZE_T, *P_XLLP_DFC_DATA_SIZE_T;

// DFC padding size enumeration transfered from/to controller
typedef enum {
    // for ReadStatus/ReadBlockLockStatus/ReadID/
    // for Read/Program disabling spare area(Both 512 and 2048)
    // for Read/Program enabling spare area, disabling ECC
    XLLP_DFC_PADDING_SIZE_0 = 0,    
    // for read/program with SPARE_EN=1, ECC_EN=0, pgSize=512
    XLLP_DFC_PADDING_SIZE_16 = 16,
    // for read/program with SPARE_EN=1, ECC_EN=1, pgSize=512 and 2048
    XLLP_DFC_PADDING_SIZE_24 = 24,
    XLLP_DFC_PADDING_SIZE_UNUSED = 0xFFFF
} XLLP_DFC_PADDING_SIZE_T, *P_XLLP_DFC_PADDING_SIZE_T;



// The low level primitives
XLLP_STATUS_T XllpFlashDfcSetGPIO(P_XLLP_DFC_CONTEXT_T pContext);

//void XllpFlashDfcSetClock(P_XLLP_DFC_CONTEXT_T pContext, XLLP_BOOL_T bEnable);

void XllpFlashDfcSetTiming(P_XLLP_DFC_CONTEXT_T pContext);

void XllpFlashDfcSetDMA(P_XLLP_DFC_CONTEXT_T pContext);

void XllpFlashDfcSetECC(P_XLLP_DFC_CONTEXT_T pContext);

void XllpFlashDfcSetSpare(P_XLLP_DFC_CONTEXT_T pContext);

XLLP_STATUS_T XllpFlashDfcGetPattern(P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT16_T cmd, P_XLLP_DFC_DATA_SIZE_T pDataSize, 
        P_XLLP_DFC_PADDING_SIZE_T pPaddingSize);

XLLP_STATUS_T XllpFlashDfcSendCommand(P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT16_T cmd, XLLP_UINT32_T addr, XLLP_UINT8_T numPages);
        
void XllpFlashDfcRun(P_XLLP_DFC_CONTEXT_T pContext);
            
void XllpFlashDfcStop(P_XLLP_DFC_CONTEXT_T pContext);

//void XllpFlashDfcClearECC(P_XLLP_DFC_CONTEXT_T pContext);

//void XllpFlashDfcClearPGCNT(P_XLLP_DFC_CONTEXT_T pContext);           
            
void XllpFlashDfcReadFIFOPartial(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T bytes,
        XLLP_DFC_DATA_SIZE_T dataSize);
            
void XllpFlashDfcWriteFIFOPartial(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T bytes,
        XLLP_DFC_DATA_SIZE_T dataSize);

void XllpFlashDfcReadFIFO(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T bytes);
            
void XllpFlashDfcWriteFIFO(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T bytes);

void XllpFlashDfcReadDFCStatus(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT32_T pStatus);
            
void XllpFlashDfcReadPageCounter(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT32_T pPageCounter);
            
void XllpFlashDfcReadBadBlockAddr(P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT32_T pBadBlockAddr);
            
void XllpFlashDfcEnableInt(P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT32_T intMask);
            
void XllpFlashDfcDisableInt(P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT32_T intMask);
            
void XllpFlashDfcClearInt(P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT32_T intMask);
            
typedef enum {
    XLLP_DFC_FLASH_NULL = 0 ,
    XLLP_DFC_FLASH_Samsung512MbX16 = 1,
    XLLP_DFC_FLASH_Micron1GbX8 = 2,
    XLLP_DFC_FLASH_Micron1GbX16= 3,
    XLLP_DFC_FLASH_STM1GbX16= 4,
    XLLP_DFC_FLASH_STM2GbX16= 5,
    XLLP_DFC_FLASH_STM70nm1GbX16= 6,
    XLLP_DFC_FLASH_Toshiba2GbX16= 7,
    XLLP_DFC_FLASH_END,
}XLLP_DFC_FLASH_TYPE;
            
// high level primitives
XLLP_STATUS_T XllpFlashDfcInit(P_XLLP_DFC_CONTEXT_T pContext, XLLP_DFC_FLASH_TYPE type);

XLLP_STATUS_T XllpFlashDfcInitNOGPIO(P_XLLP_DFC_CONTEXT_T pContext, XLLP_DFC_FLASH_TYPE type);

XLLP_STATUS_T XllpFlashDfcWrite (P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T startPage, 
        XLLP_UINT32_T numPages, XLLP_UINT32_T timeout, 
        P_XLLP_UINT32_T pBadBlockNum);
            
XLLP_STATUS_T XllpFlashDfcRead (P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pBuffer, XLLP_UINT32_T bufBytesPerPG, 
        XLLP_UINT32_T startPage, XLLP_UINT32_T numPages, 
        XLLP_UINT32_T timeout, P_XLLP_UINT32_T eccErrorPageNum);
            
XLLP_STATUS_T XllpFlashDfcErase (P_XLLP_DFC_CONTEXT_T pContext, 
        XLLP_UINT32_T startBlock, XLLP_UINT32_T numBlocks, 
        XLLP_UINT32_T timeout, P_XLLP_UINT32_T pBadBlockNum);
            
XLLP_STATUS_T XllpFlashDfcReadID (P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pMakerID, P_XLLP_UINT8_T pDevID);
            
XLLP_STATUS_T XllpFlashDfcReadStatus (P_XLLP_DFC_CONTEXT_T pContext, 
        P_XLLP_UINT8_T pStatus);

XLLP_STATUS_T XllpFlashDfcReset (P_XLLP_DFC_CONTEXT_T pContext);

XLLP_STATUS_T 
XllpFlashDfcReadLockStatus (P_XLLP_DFC_CONTEXT_T pContext, XLLP_UINT32_T block,
                            P_XLLP_UINT8_T pStatus);

XLLP_STATUS_T XllpFlashDfcLock (P_XLLP_DFC_CONTEXT_T pContext);

XLLP_STATUS_T XllpFlashDfcUnlock (P_XLLP_DFC_CONTEXT_T pContext, 
            XLLP_UINT32_T startBlock, XLLP_UINT32_T blockNum);
    
#endif //__XLLP_DFC_H           
